package de.micromata.icalour;

import java.awt.FontMetrics;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.data.ParserException;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.ComponentList;
import net.fortuna.ical4j.model.component.VEvent;

public class Utils {
	
	private static Logger LOG = Logger.getRootLogger();
	
	/**
	 * Break the String at the "/" into an array of strings
	 * then break each element of the array if the text width with the font metric is greater than max
	 * @param fontMetrics for the text
	 * @param text to break
	 * @param max width for a line
	 * @return array of strings which are breaked by "/" and if the width was too big
	 */
	public static LinkedList<String> breakText(FontMetrics fontMetrics, String text, int max) {
		String[] splittedSlashes = text.split("/");
		LinkedList<String> resultLines = new LinkedList<String>();
		for (String slashLine : splittedSlashes) {
			LinkedList<String> splittedWords = breakLongWords(fontMetrics, slashLine, max);
			for (String wordLine : splittedWords) {
				resultLines.add(wordLine);
			}
		}
		return resultLines;
	}
	
	/**
	 * Break the text into an array if the width of the text is greater than max
	 * @param fontMetrics for the text
	 * @param text to break
	 * @param max width for a line
	 * @return array of strings which are breaked if the text width was too big
	 */
	public static LinkedList<String> breakLongWords(FontMetrics fontMetrics, String text, int max) {
		int width = fontMetrics.stringWidth(text);
		LinkedList<String> multiLines = new LinkedList<String>();
		
		if (width > max) {
			String[] words = text.split(" ");
			String tmp = "";
			for (int i=0; i< words.length; i++) {
				tmp += words[i] + " ";
				if (i < words.length-1) {
					int lineWidth = fontMetrics.stringWidth(tmp+" "+words[i+1]);
					if (lineWidth > max) {
						multiLines.add(tmp);
						tmp = "";
					}
				} else {
					multiLines.add(tmp);
				}
			}
			
		} else {
			multiLines.add(text);
		}
		return multiLines;
	}
	
	/**
	 * Open the iCalendar file (on local system or with HTTP request) and build a Calendar object.
	 * 
	 * @param path to the iCalendar file
	 * @param remote: if true, it will open the file with the HTTP protocol, otherwise on the local filesystem
	 * @return Calendar object structre of th iCalendar file
	 */
	public static Calendar openIcal(String path, boolean remote) {
		BufferedReader br = null;
		Calendar calendar = null;
		CalendarBuilder builder = new CalendarBuilder();
		if (remote) {
			// open remote ical file
			URLConnection con = null;
			try {
				con = new URL(path).openConnection();
				br = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
				calendar = builder.build(br);
			} catch (MalformedURLException e1) {
				LOG.error("URL fehlerhaft");
				e1.printStackTrace();
			} catch (ParserException e) {
				LOG.error("could not import ical file");
				e.printStackTrace();
			} catch (IOException e1) {
				LOG.error("URL nicht erreichbar");
				e1.printStackTrace();
			} 
		} else {
			// open local ical file, alternative
			FileInputStream fin = null;
			InputStreamReader isr = null;
			try {
				fin = new FileInputStream(path);
				isr = new InputStreamReader(fin, "UTF8");
				calendar = builder.build(isr);
			} catch (ParserException e) {
				LOG.error("could not import ical file");
				e.printStackTrace();
			} catch (FileNotFoundException e1) {
				LOG.error("could not file local ical");
				e1.printStackTrace();
			} catch (IOException e) {
				LOG.info("file not found");
				e.printStackTrace();
			}
		}
		return calendar;
	}

	/**
	 * Sort the VEvents by Startdate with a helper class, which implement Comparable
	 * 
	 * @param ComponentList with VEvents
	 * @return new ComponentList order by Startdate
	 */
	public static ComponentList sortEvents(ComponentList todayList) {
		List<SortedVEvent> list = new ArrayList<SortedVEvent>();  
		for (Object e : todayList) {
			SortedVEvent sortedEvent = new SortedVEvent((VEvent) e);
			list.add(sortedEvent);
		}
		Collections.sort(list);
		ComponentList sortedList = new ComponentList();
		for (SortedVEvent sortedEvent : list) {
			sortedList.add(sortedEvent.getEvent());
		}
		return sortedList;
	}
}

